package com.gufe.utils;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 新增值班排班表导入Excel表工具类
 * zyw
 */
public class ImportExcelUtil {


    // 常量定义
    private static final String XLS_SUFFIX = ".xls";    // 2003版   .xls
    private static final String XLSX_SUFFIX = ".xlsx";  // 2007+版  .xlsx
    private static final String XLSM_SUFFIX = ".xlsm";  // 启用宏的Excel
    private static final String XLSB_SUFFIX = ".xlsb";  //  二进制Excel

    /*   此方法用于从Excel文件中读取所有工作表（Sheet）的数据，并转换为二维列表（List<List<Object>>）。具体流程如下：
    初始化工作簿：通过ImportExcelUtil.getWorkbook创建Workbook对象。
    遍历所有工作表：循环处理每个Sheet。
    遍历每行和每列：逐行逐列读取单元格的值，使用ImportExcelUtil.getCellValue解析单元格内容。
    存储数据：将每行数据存入List<List<Object>>中，最终返回完整数据。*/
    /**
     * 从Excel文件（支持.xls, .xlsx等格式）中读取所有工作表的数据，并转换为二维列表
     * @param in       Excel文件输入流（需确保已正确打开）
     * @param fileName 文件名（用于后缀校验和错误提示）
     * @return 包含所有工作表数据的二维列表，结构为 List<行数据List<单元格值Object>>
     * @throws IOException 当文件读取失败或格式不支持时抛出
     */
    public static List<List<Object>> getListByExcel(InputStream in, String fileName) throws IOException {
        // 初始化返回的数据列表（避免null，直接赋空列表）
        List<List<Object>> list = new ArrayList<>();

        // 使用try-with-resources自动关闭Workbook资源（确保释放内存）
        try (Workbook work = ImportExcelUtil.getWorkbook(in, fileName)) {
            // 校验工作簿是否创建成功
            if (work == null) {
                throw new IllegalArgumentException("Excel工作簿创建失败：文件可能损坏或格式不支持");
            }

            // 遍历所有工作表（Sheet）
            for (int sheetIdx = 0; sheetIdx < work.getNumberOfSheets(); sheetIdx++) {
                // 获取当前Sheet对象，跳过空Sheet
                Sheet sheet = work.getSheetAt(sheetIdx);
                if (sheet == null) {
                    continue; // 忽略空表（如隐藏表）
                }

                // 1. 获取表头行（第一行）
                Row headerRow = sheet.getRow(0);
                if (headerRow == null) {
                    // 可选：如果表头为空，跳过该Sheet或按需处理
                    continue;
                }
                // 2. 获取表头的最大列索引（lastCellNum）
                int maxHeaderCols = headerRow.getLastCellNum();



                // 使用迭代器遍历行（比索引遍历更高效，避免空行干扰）
                // 遍历所有工作表（Sheet）的每一行（row）
                Iterator<Row> rowIterator = sheet.iterator();
                while (rowIterator.hasNext()) {
                    Row row = rowIterator.next();
                    // 跳过空行（可能由文件中间空行导致）
                    if (row == null) {
                        continue;
                    }
                    // 初始化当前行数据列表
                    List<Object> rowData = new ArrayList<>();

                        // 遍历所有列（处理可能的空单元格）
                        for (int cellIdx = 0; cellIdx < maxHeaderCols; cellIdx++) {
                            // 获取单元格：若单元格为空，按策略返回null（避免MissingCellPolicy导致异常）
                            Cell cell = row.getCell(cellIdx, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
                            // 处理单元格值：空单元格转为空字符串，非空则调用工具类解析
                            Object value = (cell != null) ? ImportExcelUtil.getCellValue(cell) : "";
                            rowData.add(value);
                        }
                    // 将当前行数据添加到总列表（即使为空行也保留）
                    list.add(rowData);
                }
            }
        } catch (IOException e) {
            // 明确抛出IO异常（如文件流中断）
            throw new IOException("解析Excel文件失败，请检查文件是否被占用或损坏", e);
        } catch (Exception e) {
            // 封装其他未知异常（如POI内部错误）
            throw new RuntimeException("解析过程中发生未预期错误", e);
        }
        // 返回完整数据列表
        return list;
    }

    /**
     * 根据输入流自适应创建Workbook（支持.xls, .xlsx, .xlsm, .xlsb）
     * @param inStr   文件输入流
     * @param fileName 文件名（用于后缀校验）
     * @return Workbook对象
     * @throws Exception 如果文件格式不支持或读取失败
     */
    public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
        if (fileName == null || !fileName.contains(".")) {
            throw new IllegalArgumentException("文件名无效或缺少后缀名！");
        }

        String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        // 校验支持的格式
        if (!isSupportedFormat(fileType)) {
            throw new IllegalArgumentException("不支持的文件格式：" + fileType);
        }

        // 使用WorkbookFactory自动识别文件类型
        try {
            return WorkbookFactory.create(inStr);
        } catch (Exception e) {
            throw new Exception("解析Excel文件失败", e);
        }
    }

    /**
     * 校验文件后缀是否支持
     */
    private static boolean isSupportedFormat(String fileType) {
        return fileType.equals(XLS_SUFFIX)
                || fileType.equals(XLSX_SUFFIX)
                || fileType.equals(XLSM_SUFFIX)
                || fileType.equals(XLSB_SUFFIX);
    }

    /**
     * 描述：对表格中数值进行格式化
     */
    public  static Object getCellValue(Cell cell){
        Object value = null;
        DecimalFormat df = new DecimalFormat("0");  //格式化number String字符
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");  //日期格式化
//        DecimalFormat df2 = new DecimalFormat("0.00");  //格式化数字

        if (cell != null) {
            switch (cell.getCellType()) {
                case STRING:
                    value = cell.getRichStringCellValue().getString();
                    break;
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        // 日期类型按原逻辑处理
                        value = String.valueOf(cell.getNumericCellValue());
                    } else {
                        // 新增：数值类型特殊处理
                        double numValue = cell.getNumericCellValue();
                        if (numValue == Math.floor(numValue)) {
                            // 如果是整数，去掉小数点
                            value = String.valueOf((long) numValue);
                        } else {
                            // 非整数保留原始值
                            value = String.valueOf(numValue);
                        }
                    }
                    break;
                case BOOLEAN:
                    value = String.valueOf(cell.getBooleanCellValue());
                    break;
                case BLANK:
                    value = "";
                    break;
                default:
                    value = "";
                    break;
            }
        }

        return value;
    }
}